
import {DataContent} from './chatObject.js';

let isSocketClose = false;    // 是否关闭socket

let heartbeatInterval = null;   // 心跳定时器
let socketTask = null;//websocket对象

let  againTimer = null;//断线重连定时器

//此处变量用于断线重连的调用传参
let url = null;
let onReFn = null;
let onErrFn = null;


/**
 * socketUrl：websocket的地址
 * onReceive：消息监听的回调
 * onErrorEvent：抛出错误的回调，且弹窗连接失败的提示框
 * */
const socket = (socketUrl = 'ws://127.0.0.1:8090/ws' ,onReceive,onErrorEvent) => {
	url = socketUrl;
	onReFn= onReceive;
	onErrFn= onErrorEvent;
	isSocketClose = false;
	//判断是否有websocket对象，有的话清空
	if(socketTask){
		socketTask.close();
		socketTask = null;
		heartbeatInterval && clearInterval(heartbeatInterval);
	}

	//WebSocket的地址
	// 【非常重要】必须确保你的服务器是成功的,如果是手机测试千万别使用ws://127.0.0.1:9099【特别容易犯的错误】
	// 连接
	socketTask = uni.connectSocket({
		url: url,
		success(data) {
			againTimer && clearInterval(againTimer)//断线重连定时器
		},
		fail: (err) => {
			console.log("报错",err);
		}
	});
	// 连接打开
	socketTask.onOpen((res) => {
		// 初始化
		uni.$emit("init");
		if (heartbeatInterval == null) {
			/**
			 * 情况：部署到服务器上的websocket程序，未加心跳，发现隔一阵子就会断开，出现1006 (abnormal closure)错误。
			 	原因：代理参数的proxy_read_timeout默认是60s，只要超过这段时间没有通信，就会自动断开tcp连接
			 	解决办法：
			 	修改参数proxy_read_timeout，比如在代理设置添加 proxy_read_timeout 300s;
			 	添加心跳，心跳的间隔要小于默认的读超时proxy_read_timeout 60s，这样程序就会可以在60s的时间窗口内读到数据，不会被nginx断开连接。
			 * @type {number}
			 */
			// 50秒发送一次心跳
			heartbeatInterval = setInterval(() => {
				let heartBeatMsg = new DataContent(5, null,  'PING')
				//通过 WebSocket 连接发送数据
				socketTask.send({
					data: JSON.stringify(heartBeatMsg)
				});
			}, 1000 * 50)
		}
		againTimer && clearInterval(againTimer)//断线重连定时器
	})
	// 监听连接失败
	socketTask.onError((err) => {
		console.log("websocket 出错：" + err.errMsg)
		//停止发送心跳
		heartbeatInterval && clearInterval(heartbeatInterval)
		//如果不是人为关闭的话，进行重连
		if (!isSocketClose) {
			reconnect(url,onErrorEvent)
		}
	})

	// // 监听连接关闭 -
	socketTask.onClose((e) => {
		console.log('websocket 断开: ' + e.code + ' ' + e.reason + ' ' + e.wasClean)
		heartbeatInterval && clearInterval(heartbeatInterval);
		if (!isSocketClose) {
			reconnect(url,onErrorEvent)
		}
	})

	// 监听收到信息
	socketTask.onMessage((res) => {
		let serverData = res.data
		//与后端规定好返回值分别代表什么，写业务逻辑
		serverData && onReceive(serverData);
	});


}

const reconnect = (url,onErrorEvent) => {
	console.log('进入断线重连',isSocketClose);
	againTimer && clearInterval(againTimer)//断线重连定时器
	heartbeatInterval && clearInterval(heartbeatInterval);
	//判断是否有websocket对象，有的话清空
	if(socketTask){
		socketTask.close(); // 确保已经关闭后再重新打开
		socketTask = null;
	}
	onErrorEvent('进入断线重连...')
	// 连接  重新调用创建websocket方法
	againTimer = setInterval(()=>{
		socket(url,onReFn,onErrFn)
	},1000*5)


}

const sendMsg = (msg) => {   //向后端发送命令
	msg = JSON.stringify(msg)
	try{
		//通过 WebSocket 连接发送数据
		socketTask.send({
			data: msg
		});
	}catch(e){
		if(socketTask){
			socketTask.close({
				success(res) {
					reconnect(url,onErrFn);
				},
				fail(err) {

				}
			})
		}

	}
}
// 关闭websocket【必须在实例销毁之前关闭,否则会是undefined错误】beforeDestroy() {websocketObj.stop();}

const stop = () => {
	heartbeatInterval && clearInterval(heartbeatInterval);
	againTimer && clearInterval(againTimer)//断线重连定时器
	socketTask.close(); // 确保已经关闭后再重新打开
	socketTask = null;
}

export const websocketObj = {
	socket,
	stop,
	sendMsg
};